/*
 *  Copyright 2001-2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package ar.uba.fi.posgrado.economy.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import ar.uba.fi.posgrado.common.dao.DAOException;
import ar.uba.fi.posgrado.common.dao.NoSuchEntityException;
import ar.uba.fi.posgrado.common.exception.MissingArgumentException;
import ar.uba.fi.posgrado.common.exception.PosgradoException;
import ar.uba.fi.posgrado.common.exception.PosgradoRuntimeException;
import ar.uba.fi.posgrado.common.exception.RepeatedNameException;
import ar.uba.fi.posgrado.common.model.User;
import ar.uba.fi.posgrado.economy.dao.DiscountDAO;
import ar.uba.fi.posgrado.economy.model.Discount;
import ar.uba.fi.posgrado.economy.service.DiscountService;

/**
 * Implementacion de {@link DiscountService}
 * 
 * @author nicolas.gonzalez
 * @see DiscountService
 */
public class DiscountServiceImpl implements DiscountService {

    /** Logger */
    private static Logger logger = Logger.getLogger(DiscountServiceImpl.class);

    private final Double ZERO = 0d;
    private DiscountDAO discountDAO;
    
    /**
     * @param discountDAO the discountDAO to set
     */
    public void setDiscountDAO(DiscountDAO discountDAO) {
        this.discountDAO = discountDAO;
    }

    /**
     * @see ar.uba.fi.posgrado.common.service.GenericService#create(java.lang.Object)
     */
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void create(Discount discount) throws MissingArgumentException,
            PosgradoException {
        if ((discount.getValue().compareTo(ZERO) <= 0)
                && (discount.getPercentage().compareTo(ZERO) <= 0)) {
            throw new MissingArgumentException(
                    "Valor o Porcentaje tienen que ser "
                            + "distintos de cero y mayores que cero");
        }
        /* Analiza si no existe un descuento con la misma descripcion. En ese caso
         * arroja una RepeatedInstanceException */
        try {
            // Puede ser q el nombre de usuario exista
            this.discountDAO.findByDescription(discount.getDescription());

            throw new RepeatedNameException(
                    "El descuento con descripcion "
                            + discount.getDescription()
                            + " no es un descuento valido. Ya existe un descuento con"
                            + " esa descripcion.");
        } catch (NoSuchEntityException e) {
            // Si entro aca es xq no existia x lo cual esta bien
        }
        try {
            this.discountDAO.save(discount);
            logger.info("Descuento: " + discount + " creado con exito");
        } catch (DAOException e) {
            throw new PosgradoException("Excepcion al crear el descuento: "
                    + discount, e);
        }
    }

    /**
     * @see ar.uba.fi.posgrado.common.service.GenericService#delete(java.lang.Object)
     */
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void delete(Discount discount) throws PosgradoRuntimeException,
            PosgradoException {
        try {
            this.discountDAO.remove(discount);
            logger.info("Descuento: " + discount + ", eliminado con exito");
        } catch (DAOException e) {
            throw new PosgradoException("Excepcion eliminando el descuento: "
                    + discount, e);
        }
    }

    /**
     * @see ar.uba.fi.posgrado.common.service.GenericService#getAll()
     */
    @Transactional(readOnly = true)
    public List<Discount> getAll() throws PosgradoRuntimeException,
            PosgradoException {
        try {
            List<Discount> response = this.discountDAO.findAll();
            logger.info("Descuentos encontrados: " + response.size());
            return response;
        } catch (DAOException e) {
            throw new PosgradoException("Excepcion buscando descuentos", e);
        }
    }

    /**
     * @see ar.uba.fi.posgrado.common.service.GenericService#getById(java.lang.Long)
     */
    @Transactional(readOnly = true)
    public Discount getById(Long discountId) throws PosgradoRuntimeException,
            PosgradoException {
        try {
            Discount response = (Discount)this.discountDAO.findById(discountId);
            logger.info("Descuento con Id: " + discountId
                    + ", encontrado con exito");
            return response;
        } catch (DAOException e) {
            throw new PosgradoException(
                    "Excepcion buscando el Descuento con Id: " + discountId, e);
        }
    }

    /**
     * @see ar.uba.fi.posgrado.common.service.GenericService#update(java.lang.Object)
     */
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public Discount update(Discount discount) throws PosgradoRuntimeException,
            PosgradoException {
        if ((discount.getValue().compareTo(ZERO) <= 0)
                && (discount.getPercentage().compareTo(ZERO) <= 0)) {
            throw new MissingArgumentException(
                    "Valor o Porcentaje tienen que ser "
                            + "distintos de cero y mayores que cero");
        }
        try {
            this.discountDAO.update(discount);
        } catch (DAOException e) {
            throw new PosgradoException("Excepcion al modificar el descuento: "
                    + discount, e);
        }
        
        return discount;
    }

    /**
     * @see ar.uba.fi.posgrado.economy.service.DiscountService#getDiscountsByIds(java.util.List)
     */
    @Transactional(readOnly = true)
    public List<Discount> getDiscountsByIds(List<Long> discountIds)
            throws PosgradoRuntimeException, PosgradoException {
        List<Discount> response = new ArrayList<Discount>();
        
        for (Long discountId : discountIds) {
            response.add(this.getById(discountId));
        }
        
        return response;
    }

	/** 
	 * @see ar.uba.fi.posgrado.common.service.GenericService#filter(java.util.List, ar.uba.fi.posgrado.common.model.User)
	 */
	public List<Discount> filter(List<Discount> list, User user)
			throws PosgradoRuntimeException, PosgradoException {
		return list;
	}

}
